﻿using Shop.Model.AttrTemplate;
using Shop.Model.DB;
using Shop.RemoteModel.AttrTemplate.Model;
using Shop.Repository;
using SqlSugar;
using WeDonekRpc.Client;
using WeDonekRpc.Helper;

namespace Shop.Collect.lmpl
{
    internal class AttrTemplateCollect : IAttrTemplateCollect
    {
        private readonly IAttrTemplateRepository _Repository;

        public AttrTemplateCollect (IAttrTemplateRepository repository)
        {
            this._Repository = repository;
        }

        public long Add (AttrTemplateAdd add)
        {
            if (this._Repository.IsExist(c => c.CategoryId == add.CategoryId
            && c.ParentId == add.ParentId
            && c.Name == add.Name))
            {
                throw new ErrorException("shop.attr.template.repeat");
            }
            DBGoodsAttrTemplate attr = add.ConvertMap<AttrTemplateAdd, DBGoodsAttrTemplate>();
            attr.Sort = this._Repository.Max(a => a.CategoryId == add.CategoryId && a.ParentId == add.ParentId, a => a.Sort) + 1;
            return this._Repository.Add(attr);
        }

        public void Delete (DBGoodsAttrTemplate source)
        {
            if (source.IsEnable)
            {
                throw new ErrorException("shop.attr.already.enable");
            }
            else if (source.ParentId != 0)
            {
                this._Repository.Delete(source.Id);
                return;
            }
            long[] subId = this._Repository.Gets(a => a.ParentId == source.Id, a => a.Id);
            if (subId.IsNull())
            {
                this._Repository.Delete(source.Id);
            }
            else
            {
                this._Repository.Delete(subId.Add(source.Id));
            }
        }

        public DBGoodsAttrTemplate Get (long id)
        {
            return this._Repository.Get(id);
        }
        public Result Get<Result> (long id) where Result : class
        {
            return this._Repository.Get<Result>(id);
        }
        public AttrTemplateDto[] GetsByCategoryId (long categoryId, bool? isEnable)
        {
            if (isEnable.HasValue)
            {
                return this._Repository.Gets<AttrTemplateDto>(a => a.CategoryId == categoryId && a.IsEnable == isEnable.Value, "Sort");
            }
            return this._Repository.Gets<AttrTemplateDto>(a => a.CategoryId == categoryId, "Sort");
        }

        public void Enable (DBGoodsAttrTemplate source)
        {
            if (source.IsEnable)
            {
                return;
            }
            else if (source.ParentId == 0)
            {
                this._Repository.SetIsEnable(source.Id, true);
            }
            else
            {
                this._Repository.SetIsEnable(new long[]
                {
                    source.Id,
                    source.ParentId
                }, true);
            }
        }
        public void Stop (DBGoodsAttrTemplate source)
        {
            if (!source.IsEnable)
            {
                return;
            }
            long[] subId = this._Repository.Gets(a => a.ParentId == source.Id, a => a.Id);
            if (subId.IsNull())
            {
                this._Repository.SetIsEnable(source.Id, false);
            }
            else
            {
                this._Repository.SetIsEnable(subId.Add(source.Id), false);
            }
        }
        public Dictionary<long, int> SetSort (DBGoodsAttrTemplate template, int sort)
        {
            int num = template.Sort - sort;
            Dictionary<long, int> sorts = new Dictionary<long, int>()
            {
               {template.Id,sort }
            };
            if (Math.Abs(num) == 1)
            {
                long id = this._Repository.Get(a => a.CategoryId == template.CategoryId && a.ParentId == template.ParentId && a.Sort == sort, a => a.Id);
                if (id != 0)
                {
                    sorts.Add(id, template.Sort);
                }
            }
            else
            {
                int begin = template.Sort;
                int end = sort;
                if (begin > end)
                {
                    begin = sort;
                    end = template.Sort - 1;
                }
                else
                {
                    begin += 1;
                }
                var datas = this._Repository.Gets(a => a.CategoryId == template.CategoryId && a.ParentId == template.ParentId && SqlFunc.Between(a.Sort, begin, end), a => new
                {
                    a.Id,
                    a.Sort
                }).OrderBy(a => a.Sort).ToArray();
                if (!datas.IsNull() && datas[0].Sort == sort)
                {
                    num = num > 0 ? 1 : -1;
                    for (int i = 0; i < datas.Length; i++)
                    {
                        int next = i + 1;
                        var t = datas[i];
                        int s = t.Sort + num;
                        sorts.Add(t.Id, s);
                        if (next != datas.Length && datas[next].Sort != s)
                        {
                            break;
                        }
                    }
                }
            }
            this._Repository.SetSort(sorts);
            return sorts;
        }
        public bool Update (DBGoodsAttrTemplate source, AttrTemplateSet set)
        {
            if (source.IsEnable)
            {
                throw new ErrorException("shop.attr.already.enable");
            }
            else if (set.Name != source.Name && this._Repository.IsExist(c => c.CategoryId == source.CategoryId
            && c.ParentId == source.ParentId
            && c.Name == set.Name))
            {
                throw new ErrorException("shop.attr.template.repeat");
            }
            return this._Repository.Update(source, set);
        }
    }
}
